﻿package net.wangit.view.unit.component;

import java.util.List;
import java.util.Map;

import net.wangit.Element;
import net.wangit.MapList;
import net.wangit.context.ActionContext;
import net.wangit.framework.config.DomainsSettings;
import net.wangit.framework.expression.LabelExpression;
import net.wangit.jdbc.table.Column;
import net.wangit.jdbc.table.TableMeta;
import net.wangit.jdbc.table.TableMetaFactory;
import net.wangit.util.Checker;
import net.wangit.view.config.Layout;
import net.wangit.view.element.component.HiddenElement;
import net.wangit.view.page.PageImpl;
import net.wangit.view.page.PageWriter;
import net.wangit.view.template.Template;
import net.wangit.view.template.TemplateFactory;
import net.wangit.view.unit.UnitComponent;
import net.wangit.view.unit.UnitWriter;
import net.wangit.view.unit.grid.Card;
import net.wangit.view.unit.grid.DoubleColsGroup;
import net.wangit.view.unit.grid.FormGrid;
import net.wangit.view.unit.grid.Grid;
import net.wangit.view.unit.grid.HiddenVerticalGroup;
import net.wangit.view.unit.grid.HiddenableVerticalGroup;
import net.wangit.view.unit.grid.HorizontalFieldSet;
import net.wangit.view.unit.grid.HorizontalGroup;
import net.wangit.view.unit.grid.LeftNavigatorCard;
import net.wangit.view.unit.grid.NoLabelHorizontalGroup;
import net.wangit.view.unit.grid.TopNavigatorCard;
import net.wangit.view.unit.grid.VerticalFieldSet;
import net.wangit.view.unit.grid.VerticalGroup;
import net.wangit.view.unit.util.ValidationProcessor;
import net.wangit.view.util.Html;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


public class FormUnitWriter implements UnitWriter {

	private static final Log log = LogFactory
			.getLog(net.wangit.view.unit.component.FormUnitWriter.class);
	private static final String SWITCH_MINUS = "/common/images/unit/minus.gif";
	private static final String UNIT_ATTRIBUTE = "unit-attribute";// 标题区（操作区）边框设置
	private static final String TITLE_BORDER = "title-border";// 标题区（操作区）边框设置
	private static final String TITLE = "title";// 单元标题
	private static final String TITLE_CSS = "title-css";// 单元标题样式
	private static final String TOOLBAR = "toolbar";// 操作区元素
	private static final String TOOLBAR_CSS = "toolbar-css";// 操作区样式
	private static final String WRAPPER_ATTRIBUTE = "grid-attribute";// 表格区属性
	private static final String GRID = "grid";// 表格区内容
	private static final String CONTENT = "content";// 列表单元的分页导航
	protected static final String NAVIGATOR = "navigator";// 列表单元的分页导航
	protected FormUnit fu;
	protected Map<String, String> attributes;
	protected Grid grid;

	public FormUnitWriter() {
	}

	public void writePage(ActionContext ac, PageImpl page) throws Exception {
		PageWriter.write(ac, page);
	}

	public String writeUnit(ActionContext ac, UnitComponent uc) {
		fu = (FormUnit) uc;
		attributes = uc.getAttributes();
		addOperationalElements();
		setNavigator(ac);
		grid = getGrid(ac);
		ValidationProcessor.setInvalidFields(ac, uc);
		setAttributes(ac);
		return getTemplateImpl().combine(attributes);
	}

	protected Grid getGrid(ActionContext ac) {
		switch (fu.getLayoutMode()) {
		case Layout.NONE:
		case Layout.GROUP_NOLABEL:
			return new FormGrid(ac, fu);

		case Layout.GROUP_VERTICAL:
			return new VerticalGroup(ac, fu);

		case Layout.GROUP_VERTICAL_HIDDENABLE:
			return new HiddenableVerticalGroup(ac, fu);

		case Layout.GROUP_VERTICAL_HIDDEN:
			return new HiddenVerticalGroup(ac, fu);

		case Layout.GROUP_HORIZONTAL:
			return new HorizontalGroup(ac, fu);

		case Layout.GROUP_HORIZONTAL_NOLABEL:
			return new NoLabelHorizontalGroup(ac, fu);

		case Layout.GROUP_DOUBLE_COLS:
			return new DoubleColsGroup(ac, fu);

		case Layout.FIELD_SET_VERTICAL:
			return new VerticalFieldSet(ac, fu);

		case Layout.FIELD_SET_HORIZONTAL:
			return new HorizontalFieldSet(ac, fu);

		case Layout.CARD_TOP_NAVIGATOR:
			return new TopNavigatorCard(ac, fu);

		case Layout.CARD_LEFT_NAVIGATOR:
			return new LeftNavigatorCard(ac, fu);

		case Layout.CARD_NO_NAVIGATOR:
			return new Card(ac, fu);

		default:
			throw new UnsupportedOperationException((new StringBuilder(
					"Unsupported layoutMode: ")).append(fu.getLayoutMode())
					.toString());
		}
	}

	protected void setNavigator(ActionContext ac) {
		try {
			attributes.put("navigator", FormNavigatorUtil.getNavigatorHtml(ac,
					fu));
		} catch (Exception e) {
			log.error(e);
		}
	}

	private void setAttributes(ActionContext ac) {
		MapList data = fu.getData();
		attributes.put(FormUnitWriter.UNIT_ATTRIBUTE, getUnitTableAttribute());
		String toolbarHtml = grid.writeToolbar(ac, data);
		if (!Checker.isEmpty(toolbarHtml) || fu.isSwitchable()
				|| fu.isShowTitle()) {
			if (fu.isShowTitleBorder())
				attributes.put(FormUnitWriter.TITLE_BORDER, " class=\"TB\"");
			if (fu.isShowTitle() || fu.isSwitchable()) {
				attributes.put(FormUnitWriter.TITLE, getTitle(ac));
				attributes.put(FormUnitWriter.TITLE_CSS, fu.getTitleCss());
			}
			if (!Checker.isEmpty(toolbarHtml)) {
				attributes.put(FormUnitWriter.TOOLBAR, toolbarHtml);
				attributes.put(FormUnitWriter.TOOLBAR_CSS, fu.getToolbarCss());
			}
		}
		attributes.put(FormUnitWriter.WRAPPER_ATTRIBUTE,
				getWrapperTableAttribute());
		attributes.put(FormUnitWriter.GRID, grid.write(ac, data));
		attributes.put(FormUnitWriter.CONTENT, fu.getContent());
	}

	private String getWrapperTableAttribute() {
		StringBuffer html = new StringBuffer();
		html.append(" id=\"").append("u_w_").append(fu.getId()).append("\"");
		if (fu.isShowGridBorder())
			html.append(" class=\"").append("GB").append("\"");
		return html.toString();
	}

	private String getTitle(ActionContext ac) {
		StringBuffer html = new StringBuffer();
		if (fu.isSwitchable())
			html.append("<img onclick=$fSwitch(this) class=\"").append("SW")
					.append("\" src=\"").append(FormUnitWriter.SWITCH_MINUS)
					.append("\"").append(">&nbsp;");
		if (fu.isShowTitle())
			html.append(LabelExpression.resolve(ac, fu.getTitle()));
		return html.toString();
	}

	private String getUnitTableAttribute() {
		StringBuffer html = new StringBuffer();
		Html.set(html, fu.getTableAttribute());
		html.append(" id=\"").append("u_u_").append(fu.getId()).append("\"");
		if (fu.isShowUnitBorder())
			html.append(" class=\"").append("UB").append("\"");
		int width = fu.getWidth();
		if (width > 0)
			Html.setWidth(html, width, fu.getWidthMode());
		else
			html.append(" width=\"100%\"");
		Html.setHeight(html, fu.getHeight(), fu.getHeightMode());
		return html.toString();
	}

	protected void addOperationalElements() {
		String tableName = fu.getTableName();
		if (!fu.isOperable() || Checker.isEmpty(tableName) || fu.size() == 0)
			return;
		TableMeta meta = TableMetaFactory.getTableMeta(fu.getDomain(),
				tableName);
		MapList data = fu.getData();
		HiddenElement operator = new HiddenElement("", fu.getOperator());
		operator.setTdColSpan(0);
		fu.addElement(operator);
		List<Column> columns = meta.getPrimaryKey().getColumns();
		for (int i = 0; i < columns.size(); i++) {
			String name = columns.get(i).getName();
			HiddenElement primaryKey = new HiddenElement((new StringBuilder(
					String.valueOf(name))).append(".k").toString());
			setDefaultValue(primaryKey, data, name);
			primaryKey.setTdColSpan(0);
			fu.addElement(primaryKey);
		}

		Column versionColumn = meta.getVersionColumn();
		if (versionColumn != null) {
			String name = versionColumn.getName();
			HiddenElement version = new HiddenElement((new StringBuilder(String
					.valueOf(name))).append(".v").toString());
			setDefaultValue(version, data, name);
			version.setTdColSpan(0);
			fu.addElement(version);
		}
	}

	private void setDefaultValue(Element element, MapList data, String name) {
		if (!Checker.isEmpty(data)) {
			for (int i = 0; i < data.size(); i++)
				element.setDefaultValue(i, data.getRow(i).get(name));

		}
	}

	private Template getTemplateImpl() {
		String template = fu.getTemplate();
		if (Checker.isEmpty(template))
			template = DomainsSettings.getUnitTemplate(fu.getDomain());
		return TemplateFactory.getTemplate(template);
	}

}
